# uncompyle6 version 3.9.2
# Python bytecode version base 3.6 (3379)
# Decompiled from: Python 3.10.10 (tags/v3.10.10:aad5f6a, Feb  7 2023, 17:20:36) [MSC v.1929 64 bit (AMD64)]
# Embedded file name: modules\common\Device.py
import json, os, re, string, traceback
from concurrent.futures import ThreadPoolExecutor, as_completed
from modules.common.Command_exec import execute_cmd, exec_cmd
from modules.common.Decorators import running_time
from modules.common.GlobalAttrs import *
from modules.common.Path import PathManager

def get_connected_device():
    cmdline = "adb devices"
    rlt = execute_cmd(cmdline)
    sn_list = []
    regex = re.compile("[A-Za-z0-9]+\\s+device")
    regex_sn = re.compile("[A-Za-z0-9]+")
    for line in rlt:
        line = line.decode().strip()
        if regex.match(line):
            sn = regex_sn.match(line).group()
            sn_list.append(sn)

    return sn_list


def get_connected_device_status():
    regexOnline = re.compile("[A-Za-z0-9]+\\s+device")
    regexOffline = re.compile("[A-Za-z0-9]+\\s+offline")
    regexRecovery = re.compile("[A-Za-z0-9]+\\s+recovery")
    regexUnauthorized = re.compile("[A-Za-z0-9]+\\s+unauthorized")
    regex_sn = re.compile("[A-Za-z0-9]+")
    deviceStatusDict = {}
    cmdline = [
     "adb", "devices"]
    rlt = exec_cmd(cmdline)
    for line in rlt:
        try:
            line = line.decode().strip()
            if regexOnline.match(line):
                sn = regex_sn.match(line).group()
                if sn in deviceStatusDict:
                    deviceStatusDict[sn] = DEVICE_STATUS_DUPLICATED
                else:
                    deviceStatusDict[sn] = DEVICE_STATUS_ONLINE
            if regexOffline.match(line):
                sn = regex_sn.match(line).group()
                if sn in deviceStatusDict:
                    deviceStatusDict[sn] = DEVICE_STATUS_DUPLICATED
                else:
                    deviceStatusDict[sn] = DEVICE_STATUS_OFFLINE
            if regexRecovery.match(line):
                sn = regex_sn.match(line).group()
                if sn in deviceStatusDict:
                    deviceStatusDict[sn] = DEVICE_STATUS_DUPLICATED
                else:
                    deviceStatusDict[sn] = DEVICE_STATUS_RECOVERY
            if regexUnauthorized.match(line):
                sn = regex_sn.match(line).group()
                if sn in deviceStatusDict:
                    deviceStatusDict[sn] = DEVICE_STATUS_DUPLICATED
                else:
                    deviceStatusDict[sn] = DEVICE_STATUS_UNAUTHORIZED
        except:
            pass

    return deviceStatusDict


@running_time
def get_pm_list_packages(sn):
    package_info_list = []
    label_package_dict = {}
    package_label_dict = {}
    package_label_json_file = os.path.join(PathManager.tools_folder, "package_label.json")
    if os.path.isfile(package_label_json_file):
        with open(package_label_json_file, "r", encoding="utf-8") as f:
            try:
                package_label_dict = json.load(f)
            except:
                traceback.print_exc()

    cmdline = [
     "adb", "-s", sn, "shell", "pm list packages -f"]
    startStr = "package:"
    rlt = exec_cmd(cmdline)
    for line in rlt:
        try:
            line = line.decode().strip()
            if line.startswith(startStr):
                line = line.split(":")[1]
                package_path = line.rsplit("=", 1)[0]
                package_name = line.rsplit("=", 1)[1]
                if package_name in package_label_dict:
                    label_package_dict[package_label_dict[package_name]] = package_name
                else:
                    package_info_list.append([package_path, package_name])
        except:
            traceback.print_exc()

    if package_info_list:
        cmdline = ["adb", "-s", sn, "push", "tools/aapt-arm-pie", "/data/local/tmp"]
        exec_cmd(cmdline)
        cmdline = [
         "adb", "-s", sn, "shell", "chmod +x /data/local/tmp/aapt-arm-pie"]
        exec_cmd(cmdline)
        with ThreadPoolExecutor(max_workers=20, thread_name_prefix="get_package_info_by_aapt") as executor:
            scan_thread_list = [executor.submit(get_package_info_by_aapt, sn, package_path, package_name) for package_path, package_name in package_info_list]
            for future in as_completed(scan_thread_list):
                package_label, package_name = future.result()
                print(package_label, package_name)
                label_package_dict[package_label] = package_name
                package_label_dict[package_name] = package_label

    with open(package_label_json_file, "w", encoding="utf-8") as f:
        try:
            json.dump(package_label_dict, f)
        except:
            traceback.print_exc()

    return label_package_dict


def get_package_info_by_aapt(sn, package_path, package_name):
    package_label = package_name
    cmdline = ["adb", "-s", sn, "shell", "/data/local/tmp/aapt-arm-pie d badging {}".format(package_path)]
    rlt = exec_cmd(cmdline)
    for line in rlt:
        try:
            line = line.decode().strip()
            if "application-label:" in line:
                application_label = line.split("'")[1].strip()
                if application_label != "":
                    package_label = application_label
                continue
            if "application-label-zh-CN:" in line:
                application_label_cn = line.split("'")[1].strip()
                if application_label_cn != "":
                    package_label = application_label_cn
            break
        except:
            traceback.print_exc()

    return (
     package_label, package_name)


def get_device_info(sn):
    android_dict = {
     '21': '"Android 5.0 Lollipop"', '22': '"Android 5.1 Lollipop"', 'MNC': '"Android MNC Preview"', 
     '23': '"Android 6.0 Marshmallow"', '24': '"Android 7.0 Nougat"', '25': '"Android 7.1.1 Nougat"', 
     '26': '"Android 8.0 Oreo"', '27': '"Android 8.1 Oreo"', '28': '"Android API 28"', 
     'Q': '"Android Q Preview"', '29': '"Android 9.+ Q"'}
    product, ic, android_version, brand, build, build_text = ('None', 'None', 'None',
                                                              'None', 'None', 'None')
    cmdline = "adb -s {} shell getprop".format(sn)
    rlt_lines = execute_cmd(cmdline)
    for line in rlt_lines:
        line = line.decode().strip()
        if "ro.product.model" in line:
            product = "product=" + line.split(":")[1].strip().strip(string.punctuation)
        if "ro.hardware" in line:
            ic = "ic=" + line.split(":")[1].strip().strip(string.punctuation)
        if "ro.build.version.sdk" in line:
            android_sdk = line.split(":")[1].strip().strip(string.punctuation)
            try:
                android_version = "android=" + android_dict.get(android_sdk)
            except:
                pass

            if "ro.product.manufacturer" in line:
                brand = "brand=" + line.split(":")[1].strip().strip(string.punctuation)
            if "ro.build.display.id" in line:
                build = line.split(":")[1].strip().strip(string.punctuation)
                build_text = "build=" + line.split(":")[1].strip().strip(string.punctuation)

    project = "None"
    if build:
        build_splited = build.split("-")
        if len(build_splited) == 4:
            project = build_splited[0] + "-" + build_splited[1] + "-" + build_splited[2]
        elif len(build_splited) == 5:
            project = build_splited[0] + "-" + build_splited[1] + "-" + build_splited[2] + "-" + build_splited[3]
    ram_g = "None"
    cmdline = "adb -s {} shell dumpsys meminfo".format(sn)
    rlt_lines = execute_cmd(cmdline)
    for line in rlt_lines:
        line = line.decode().strip()
        if "Total RAM" in line:
            try:
                ram = int("".join(re.findall("\\d+", line)))
                ram_g = str(ram / 1024 / 1024)
                if ram > 3:
                    ram_g = "ram=4G"
                elif ram > 2:
                    ram_g = "ram=3G"
                else:
                    ram_g = "ram=1G"
            except:
                ram_g = "None"

    rom_g = "None"
    cmdline = "adb -s {} shell df".format(sn)
    rlt_lines = execute_cmd(cmdline)
    for line in rlt_lines:
        line = line.decode().strip()
        if line.endswith("/data"):
            try:
                rom = int(line.split()[1]) / 1024 / 1024
                if rom > 128:
                    rom_g = "rom=256G"
                elif rom > 64:
                    rom_g = "rom=128G"
                elif rom > 32:
                    rom_g = "rom=64G"
                elif rom > 16:
                    rom_g = "rom=32G"
                elif rom > 8:
                    rom_g = "rom=16G"
                else:
                    if rom > 4:
                        rom_g = "rom=8G"
            except:
                rom_g = "None"

    info_list = [
     brand, product, build_text, ic, android_version, ram_g, rom_g, 
     build, project]
    return info_list


def get_device_info_new(sn):
    product, ic, android_sdk, brand, build, abi, screenSize, ram_g, rom_g = (None,
                                                                             None,
                                                                             None,
                                                                             None,
                                                                             None,
                                                                             None,
                                                                             None,
                                                                             None,
                                                                             None)
    cmdline = ['adb', '-s', sn, 'shell', 'getprop']
    rlt = exec_cmd(cmdline)
    for line in rlt:
        try:
            line = line.decode().strip()
            if "[ro.product.model]" in line:
                product = line.split(":")[1].strip().strip(string.punctuation)
            if "[ro.hardware]" in line:
                ic = line.split(":")[1].strip().strip(string.punctuation)
            if "[ro.build.version.sdk]" in line:
                android_sdk = line.split(":")[1].strip().strip(string.punctuation)
            if "[ro.product.manufacturer]" in line:
                brand = line.split(":")[1].strip().strip(string.punctuation)
            if "[ro.build.display.id]" in line:
                build = line.split(":")[1].strip().strip(string.punctuation)
            if "[ro.product.cpu.abi]" in line:
                abi = line.split(":")[1].strip().strip(string.punctuation)
        except:
            traceback.print_exc()

    regex = re.compile("\\d+x\\d+")
    cmdline = ['adb', '-s', sn, 'shell', 'dumpsys window']
    rlt = exec_cmd(cmdline)
    for line in rlt:
        try:
            line = line.decode().strip()
            if "init=" in line:
                screenSize = re.search(regex, line).group()
                break
        except:
            traceback.print_exc()

    cmdline = ['adb', '-s', sn, 'shell', 'dumpsys meminfo']
    rlt = exec_cmd(cmdline)
    for line in rlt:
        try:
            line = line.decode().strip()
            if "Total RAM" in line:
                ram = int("".join(re.findall("\\d+", line))) / 1024 / 1024
                if ram > 7:
                    ram_g = 8
                elif ram > 5:
                    ram_g = 6
                elif ram > 3:
                    ram_g = 4
                elif ram > 2:
                    ram_g = 3
                elif ram > 1:
                    ram_g = 2
                else:
                    ram_g = 1
        except:
            traceback.print_exc()

    cmdline = ['adb', '-s', sn, 'shell', 'df']
    rlt = exec_cmd(cmdline)
    for line in rlt:
        try:
            line = line.decode().strip()
            if line.endswith("/data"):
                rom = int(line.split()[1]) / 1024 / 1024
                if rom > 128:
                    rom_g = 256
                elif rom > 64:
                    rom_g = 128
                elif rom > 32:
                    rom_g = 64
                elif rom > 16:
                    rom_g = 32
                elif rom > 8:
                    rom_g = 16
                elif rom > 4:
                    rom_g = 8
        except:
            traceback.print_exc()

    return (
     brand, product, ic, abi, android_sdk, screenSize, ram_g, rom_g, build)


def get_package_pid(sn, package_name):
    """
    获取指定 sn 手机中，指定 package_name 的pid
    :param sn:
    :param package_name:
    :return:
    """
    regex_pid = re.compile("(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+\\d{2}:\\d{2}:\\d{2}")
    cmdline = ["adb", "-s", sn, "shell", "ps -ef | grep {} | grep -v grep".format(package_name)]
    rlt = exec_cmd(cmdline)
    for line in rlt:
        line = line.decode().strip()
        regex_rlt = re.search(regex_pid, line)
        if regex_rlt:
            return int(regex_rlt.group(1))


if __name__ == "__main__":
    print(get_device_info("H623CB7J01234567"))
